﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Windows;
using SyncList.Business.ValueObject;
using SyncList.Business;

namespace SyncList.Scanner
{

    /// <summary>
    /// Responsable du Scan des fichiers
    /// </summary>
    class FileScanner
    {

        /// <summary>
        /// Calculateur de Hash
        /// </summary>
        private IHashService _hash;



        /// <summary>
        /// Scanner un dossier
        /// </summary>
        /// <param name="collection">Collection à remplir</param>
        /// <param name="maxCount">Nombre maximum à scanner</param>
        /// <param name="folder">Dossier</param>
        /// <param name="filter">Filtres comme la taille mini pour prendre en compte le fichier</param>
        /// <param name="mustStop">Pas forcément propre, sémaphore indiquant si l'on souhaite nous voir arrêter le traitement</param>
        /// <returns></returns>        
        public int Scan(FileDefCollection collection, string folder, FileFilter filter, int maxCount, TimeSpan timeOut, ref bool mustStop)
        {
            _hash = ServiceAccessor.HashService;

            string doublonsFolder = "#DOUBLONS";

            DateTime start = DateTime.Now;

            int count = 0;
            string[] files = Directory.GetFiles(folder, "*", SearchOption.AllDirectories);
            foreach (string fileName in files)
            {
                if (fileName.Contains(@"\" + doublonsFolder + @"\")) // Ignorer le sous-dossier réservé aux doublons! Sinon on boucle !!!
                    continue;

                int i = fileName.LastIndexOf(@"\");
                string nameOnly = fileName.Substring(i + 1);
                string folderOnly = fileName.Substring(0, i);

                // - Ignorer les éléments déjà faits
                FileDef found = collection.FirstOrDefault(c => c.Name.Equals(nameOnly) && c.LocalFolder.Equals(folderOnly));
                if (found == null)
                {

                    FileDef def = _hash.ComputeFileHash(folderOnly, nameOnly, filter);
                    if (def != null)
                    {

                        // - Rechercher le Hash dans la collection (si un film a été renommé)
                        found = collection.FirstOrDefault(c => c.Hash.Equals(def.Hash));
                        if (found == null)
                        {
                            // - Ajouter un élément qui n'existe pas
                            collection.Add(def);
                        }
                        else
                        {
                            // - Ajouter à la collection de doublons et ignorer si l'ancien fichier existe encore
                            string previousFile = found.LocalFolder + @"\" + found.Name;
                            string newFile = fileName;
                            if (File.Exists(previousFile))
                            {
                                //MessageBox.Show("Il y a un doublons entre " + newFile + " et " + previousFile + ". Déplacement d'un des 2 fichiers dans #DOUBLONS");

                                string doublons = folder + @"\" + doublonsFolder;
                                if(!Directory.Exists(doublons))
                                    Directory.CreateDirectory(doublons);

                                string targetBase = doublons + @"\" + nameOnly;
                                string target = targetBase;

                                string extension = "";
                                int posExt = targetBase.LastIndexOf(".");
                                if(posExt >= 0)
                                {
                                    extension = targetBase.Substring(posExt);
                                    targetBase = targetBase.Substring(0, posExt);
                                }

                                int index = 1;
                                while (File.Exists(target))
                                {
                                    target = targetBase + "." + index.ToString() + extension;
                                    index++;
                                }

                                File.Move(newFile, target);
                            }
                            else
                            {
                                // - Remplacer un élément par un autre
                                int index = collection.IndexOf(found);  // Position de l'élément à remplacer
                                collection.Remove(found); // Enlever l'ancien
                                collection.Insert(index, def); // Ajouter le nouveau
                            }
                        }

                        Debug.WriteLine(def.Name + " Size:" + def.Size.ToString() + " Hash: " + def.Hash);


                        // --- Conditions d'arrêt

                        // - Nombre de max de fichiers en une fois
                        count++;
                        if (maxCount > 0)
                        {
                            maxCount--;
                            if (maxCount == 0) break;
                        }

                        // - Temps en une fois
                        if (timeOut.Ticks > 0)
                        {
                            if (DateTime.Now.Ticks > (start + timeOut).Ticks)
                                break;
                        }

                        // - Arrêt utilisateur
                        if (mustStop)
                            break;

                    }
                }
            }
            return (count);
        }


      

    }
}
